package com.base.generator;

import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.internal.util.StringUtility;

public class MyGeneratorPlugin extends PluginAdapter {
	
	private Set<String> daoSet = new HashSet<String>();
	private Set<String> mapperAnnotationSet = new HashSet<String>();
	private Set<String> modelSet = new HashSet<String>();
    private boolean caseSensitive = false;

	@Override
	public boolean validate(List<String> warnings) {
		// TODO Auto-generated method stub
		return true;
	}
	
	@Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
        
        String dao = this.properties.getProperty("dao");
        String mapperAnnotation = this.properties.getProperty("mapperAnnotation");
        String models = this.properties.getProperty("models");
        //!=null || length > 0
        if (StringUtility.stringHasValue(dao)) {
            for (String mapper : dao.split(",")) {
                this.daoSet.add(mapper);
            }
        } else {
            throw new RuntimeException("Mapper 插件缺少必要的 dao 属性!");
        }
        
        if (StringUtility.stringHasValue(mapperAnnotation)) {
            for (String annotation : mapperAnnotation.split(",")) {
                this.mapperAnnotationSet.add(annotation);
            }
        } else {
            throw new RuntimeException("Mapper 插件缺少必要的 annotation 属性!");
        }
        
        if (StringUtility.stringHasValue(models)) {
            for (String model : models.split(",")) {
                this.modelSet.add(model);
            }
        } else {
            throw new RuntimeException("Entity 插件缺少必要的 model 属性!");
        }
        
        
        String caseSensitive = this.properties.getProperty("caseSensitive");
        if (StringUtility.stringHasValue(caseSensitive)) {
            this.caseSensitive = caseSensitive.equalsIgnoreCase("TRUE");
        }
    }
	
	@Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
		
		FullyQualifiedJavaType entityType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
		
		//import接口
		for (String dao : daoSet) {
			interfaze.addImportedType(new FullyQualifiedJavaType(dao));
			interfaze.addSuperInterface(new FullyQualifiedJavaType(dao + "<"
					+ entityType.getShortName() + ">"));
		}
		
		for (String annotation : mapperAnnotationSet) {
			interfaze.addImportedType(new FullyQualifiedJavaType(annotation));
			String annotationName = annotation.substring(annotation.lastIndexOf(".") + 1);
			interfaze.addAnnotation("@" + annotationName);
		}
		
		//import实体类
        interfaze.addImportedType(entityType);
		
        return true;
    }
	
	@Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable) {

		FullyQualifiedJavaType entityType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
		
		//import接口
		for (String model : modelSet) {
			topLevelClass.addImportedType(new FullyQualifiedJavaType(model));
			topLevelClass.setSuperClass(new FullyQualifiedJavaType(model + "<"
					+ entityType.getShortName() + ">"));
		}

		generateSerialFiled(topLevelClass);
    	generateGetPrimaryKeyValue(topLevelClass, introspectedTable);
    	generateSetPrimaryKeyValue(topLevelClass, introspectedTable);

        return true;
    }

    @Override
    public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable) {
    	generateSerialFiled(topLevelClass);
    	generateGetPrimaryKeyValue(topLevelClass, introspectedTable);
    	generateSetPrimaryKeyValue(topLevelClass, introspectedTable);

        return true;
    }

    @Override
    public boolean modelRecordWithBLOBsClassGenerated(
            TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    	generateSerialFiled(topLevelClass);
    	generateGetPrimaryKeyValue(topLevelClass, introspectedTable);
    	generateSetPrimaryKeyValue(topLevelClass, introspectedTable);

        return true;
    }
	
	protected void generateGetPrimaryKeyValue(TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable) {
        Method method = new Method();
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setReturnType(FullyQualifiedJavaType.getStringInstance());
        method.setName("getPrimaryKeyValue"); //$NON-NLS-1$
        
        if (introspectedTable.isJava5Targeted()) {
            method.addAnnotation("@Override"); //$NON-NLS-1$
        }

        context.getCommentGenerator().addGeneralMethodComment(method,
                introspectedTable);

        String primarykeyName = introspectedTable.getPrimaryKeyColumns().get(0).getJavaProperty();
        
        method.addBodyLine("return this." + primarykeyName + ";"); //$NON-NLS-1$

        topLevelClass.addMethod(method);
    }
	
	protected void generateSetPrimaryKeyValue(TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable) {
        Method method = new Method();
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setName("setPrimaryKeyValue"); 
        method.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "primaryKeyValue"));
        
        if (introspectedTable.isJava5Targeted()) {
            method.addAnnotation("@Override");
        }

        context.getCommentGenerator().addGeneralMethodComment(method,
                introspectedTable);

        String primarykeyName = introspectedTable.getPrimaryKeyColumns().get(0).getJavaProperty();
        
        method.addBodyLine("this." + primarykeyName + " = primaryKeyValue;"); //$NON-NLS-1$

        topLevelClass.addMethod(method);
    }
	
	protected void generateSerialFiled(TopLevelClass topLevelClass) {
        Field field = new Field("serialVersionUID=1L", new FullyQualifiedJavaType("long"));
        field.setVisibility(JavaVisibility.PRIVATE);
        field.setStatic(true);
        field.setFinal(true);

        topLevelClass.addField(field);
    }

}
